# S32K144EVB_Uart_Bootloader_GUI
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
import serial
import time
import threading

class mainGUI:
    def __init__(self):
        # settings of window
        window = tk.Tk()
        window.title("S32K144EVB_Uart_Bootloader_GUI")
        window.geometry("468x500")
        window.resizable(0,0)
        window.iconbitmap("AutoFAE.ico")
        
        # a frame contains COM's information, start/stop button, and select files button/label
        frame_COMinf = tk.Frame(window)
        frame_COMinf.grid(row = 1, column = 1)

        labelCOM = tk.Label(frame_COMinf,text="Port: ")
        self.COM = tk.StringVar(value = "COM15")
        ertryCOM = tk.Entry(frame_COMinf, textvariable = self.COM)
        labelCOM.grid(row = 1, column = 1, padx = 5, pady = 3)
        ertryCOM.grid(row = 1, column = 2, padx = 5, pady = 3)

        labelBaudrate = tk.Label(frame_COMinf,text="Baudrate: ")
        self.Baudrate = tk.IntVar(value = 19200)
        ertryBaudrate = tk.Entry(frame_COMinf, textvariable = self.Baudrate)
        labelBaudrate.grid(row = 1, column = 3, padx = 5, pady = 3)
        ertryBaudrate.grid(row = 1, column = 4, padx = 5, pady = 3)

        labelParity = tk.Label(frame_COMinf,text="Parity: ")
        self.Parity = tk.StringVar(value ="NONE")
        comboParity = ttk.Combobox(frame_COMinf, width = 17, textvariable=self.Parity)
        comboParity["values"] = ("NONE","ODD","EVEN","MARK","SPACE")
        comboParity["state"] = "readonly"
        labelParity.grid(row = 2, column = 1, padx = 5, pady = 3)
        comboParity.grid(row = 2, column = 2, padx = 5, pady = 3)

        labelStopbits = tk.Label(frame_COMinf,text="Stopbits: ")
        self.Stopbits = tk.StringVar(value ="1")
        comboStopbits = ttk.Combobox(frame_COMinf, width = 17, textvariable=self.Stopbits)
        comboStopbits["values"] = ("1","1.5","2")
        comboStopbits["state"] = "readonly"
        labelStopbits.grid(row = 2, column = 3, padx = 5, pady = 3)
        comboStopbits.grid(row = 2, column = 4, padx = 5, pady = 3)

        self.buttonSelect = tk.Button(frame_COMinf, text="Select Files", relief="raised", command=self.processButtonSelect)
        self.buttonSelect.grid(row = 3, column = 1, padx = 5, pady = 3)
        self.labelFile = tk.Label(frame_COMinf, anchor = "w", relief="sunken", width = 30, wraplength = 200, justify = "left")
        self.labelFile.grid(row = 3, column = 2, columnspan = 2, padx = 5, pady = 3, sticky = tk.W)
        self.fileName = ""
        
        self.buttonSS = tk.Button(frame_COMinf, text = "Start", command = self.processButtonSS)
        self.buttonSS.grid(row = 3, column = 4, padx = 5, pady = 3, sticky = tk.E)

        # a frame contains text which indicates status of sending
        frameAppFile = tk.Frame(window)
        frameAppFile.grid(row = 2, column = 1)
        labelOutText = tk.Label(frameAppFile,text="Status Of Data Sent:")
        labelOutText.grid(row = 1, column = 1, padx = 3, pady = 2, sticky = tk.W)
        frameAppFileSon = tk.Frame(frameAppFile)
        frameAppFileSon.grid(row = 2, column =1)
        scrollbarAppFile = tk.Scrollbar(frameAppFileSon)
        scrollbarAppFile.pack(side = tk.RIGHT, fill = tk.Y)
        self.OutputText = tk.Text(frameAppFileSon, wrap = tk.WORD, width = 60, height = 20, yscrollcommand = scrollbarAppFile.set)
        self.OutputText.pack()
        scrollbarAppFile.config(command = self.OutputText.yview)

        frameCreateInfo = tk.Frame(window)
        frameCreateInfo.grid(row = 3, column = 1)
        self.progressbarSend=ttk.Progressbar(frameCreateInfo)
        self.progressbarSend.grid(row = 0, column = 0)
        self.progressbarSend['length']=200
        buttonClear = tk.Button(frameCreateInfo, text = "Clear", command = self.ClearOutText)
        buttonClear.grid(row = 0, column = 1)
        labelAuthorText = tk.Label(frameCreateInfo, anchor = "e", width= 60, text="Author : Yingming", fg = "blue")
        labelAuthorText.grid(row = 1)

        # serial object
        self.ser = serial.Serial()
        self.uartState = False

        # serial write threading
        self.WriteUARTThread = threading.Thread(target=self.WriteUART, daemon=True)
        self.WriteUARTThread.start()
        
        window.mainloop()

    def processButtonSelect(self):
        self.fileName = filedialog.askopenfilename(filetypes = [("SREC","*.srec")])
        if self.fileName != "":
            self.labelFile.config(text = self.fileName)
            appFile = open(self.fileName, mode="r")
            self.str_appFile = appFile.readlines()
            appFile.close()
        else:
            self.labelFile.config(text = "You have not selected any files!")
        


    def processButtonSS(self):
        if (self.uartState):
            self.ser.close()
            self.buttonSS["text"] = "Start"
            self.uartState = False
        else:
            # restart serial port
            self.ser.port = self.COM.get()
            self.ser.baudrate = self.Baudrate.get()
            
            strParity = self.Parity.get()
            if (strParity=="NONE"):
                self.ser.parity = serial.PARITY_NONE
            elif(strParity=="ODD"):
                self.ser.parity = serial.PARITY_ODD
            elif(strParity=="EVEN"):
                self.ser.parity = serial.PARITY_EVEN
            elif(strParity=="MARK"):
                self.ser.parity = serial.PARITY_MARK
            elif(strParity=="SPACE"):
                self.ser.parity = serial.PARITY_SPACE
                
            strStopbits = self.Stopbits.get()
            if (strStopbits == "1"):
                self.ser.stopbits = serial.STOPBITS_ONE
            elif (strStopbits == "1.5"):
                self.ser.stopbits = serial.STOPBITS_ONE_POINT_FIVE
            elif (strStopbits == "2"):
                self.ser.stopbits = serial.STOPBITS_TWO
            
            try:
                self.ser.open()
            except:
                infromStr = "Can't open "+self.ser.port
                messagebox.showinfo(title='Warning', message=infromStr)
            
             # the COMx was open
            if self.ser.isOpen():
                self.buttonSS["text"] = "Stop"
                self.uartState = True

    def ClearOutText(self):
        self.OutputText.delete("1.0",tk.END)

    def WriteUART(self):
        while True:
            try:        
                if ((self.uartState) and (self.fileName != "")):
                    self.OutputText.insert(tk.END,"Start sending the file !\r\n")
                    self.progressbarSend['maximum']=len(self.str_appFile)
                    for appFile_line in range(len(self.str_appFile)):
                        self.progressbarSend["value"] = appFile_line + 1
                        strToSend = self.str_appFile[appFile_line].strip()
                        self.OutputText.insert(tk.END,"The data of line "+str(appFile_line+1)+ " was sent!\r\n")
                        # dispaly update
                        self.OutputText.yview_moveto(1)
                        bytesToSend_type = strToSend[0:2].encode(encoding='ASCII')
                        self.ser.write(bytesToSend_type)
                        bytesToSend_data = bytes.fromhex(strToSend[2:])
                        self.ser.write(bytesToSend_data)
                        time.sleep(0.05)
                        bytesErrCode = self.ser.read_all()
                        # when CRC error occurs, value of read_all() is b'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'
                        intErrCode = bytesErrCode[0]
                        #print(appFile_line,bytesErrCode)

                        # CRC error
                        while(intErrCode != 0x41):
                            #  line 2-N (not S0) CRC error occurs
                            if((intErrCode == 0x45) and (appFile_line != 0x00)):
                                self.OutputText.insert(tk.END,"The data of line "+str(appFile_line+1)+ " was sent!\r\n")
                                self.ser.write(bytesToSend_type)
                                self.ser.write(bytesToSend_data)
                                time.sleep(0.05)
                                bytesErrCode = self.ser.read_all()
                                intErrCode = bytesErrCode[0]
                            # other error
                            else:
                                intErrCode = 0x41
                                self.OutputText.insert(tk.END,"line "+str(appFile_line+1)+ "  send fail or too long !!!\r\n")

                    self.OutputText.insert(tk.END,"The file was sent successfully !\r\n")
                    self.ser.close()
                    self.buttonSS["text"] = "Start"
                    self.uartState = False

                # The COMx was open but the file has not be selected
                elif((self.uartState) and (self.fileName == "")):
                    messagebox.showinfo(title='Warning', message="You have not selected any files!")
                    self.ser.close()
                    self.buttonSS["text"] = "Start"
                    self.uartState = False

            except:
                self.OutputText.insert(tk.END,"Stop sending the file !\r\n")                
                                 
mainGUI()
